package tfts

import (
	"fmt"
	"github.com/spf13/viper"
	"log"
	"strconv"
	"strings"
)

var buffParser = map[string]func(i int) *attrMeta{
	"ap":  AP,
	"as":  AS,
	"ar":  AR,
	"dr":  DR,
	"hit": Hit,
	"blk": Block,
}

var apScaling = "ap*"

var transfer = map[string]string{"atk": "attack", "as": "speed", "": "time", "sec": "time"}

var champions = make(map[string]*ChampionConfig)
var bundles = make(map[string]*Bundle)

type Bundle struct {
	*championMeta
	*skill
}

type ChampionConfig struct {
	Name    string
	Speed   float64
	Mana    int            `mapstructure:"Mana"` // 初始蓝量
	Loop    bool           `mapstructure:"Loop"`
	Defence *DefenceConfig `mapstructure:"Def"`
	Skills  []*SkillConfig `mapstructure:"Skills"`
}

type DefenceConfig struct {
	Hp         int `mapstructure:"Hp"`
	Armor      int `mapstructure:"Ar"`
	Durability int `mapstructure:"Dr"`
	HealAmp    int `mapstructure:"Heal"`
	ShieldAmp  int `mapstructure:"Shield"`
	RecoverAmp int `mapstructure:"Recover"`
	HitRecover int `mapstructure:"Hit"`
	Block      int `mapstructure:"Blk"`
}

type SkillConfig struct {
	Mana     int         `mapstructure:"Mana"`
	Swing    int         `mapstructure:"Swing"`
	Shield   string      `mapstructure:"Shield"`
	Duration int         `mapstructure:"Duration"` // 护盾持续时间
	Heal     string      `mapstructure:"Heal"`
	Grow     string      `mapstructure:"Grow"`
	Buff     *BuffConfig `mapstructure:"Buff"`
}

type BuffConfig struct {
	Effect   string `mapstructure:"Effect"` // "Atk(200), AS(125)"
	Duration int    `mapstructure:"Duration"`
	Reduce   string `mapstructure:"Reduce"`
}

func ReadQuickConfig(path string) {
	// 初始化Viper
	v := viper.New()
	v.SetConfigName(path)   // 配置文件名称 (不含扩展名)
	v.SetConfigType("yaml") // 配置文件类型
	v.AddConfigPath(".")    // 在当前目录查找配置文件

	// 读取配置文件
	if err := v.ReadInConfig(); err != nil {
		log.Fatalf("读取配置文件失败: %v", err)
	}

	// 获取所有英雄名称
	heroNames := v.AllSettings()
	if len(heroNames) == 0 {
		log.Fatal("配置文件中未找到英雄数据")
	}

	// 解析每个英雄
	for name := range heroNames {
		// 获取英雄配置子树
		heroViper := v.Sub(name)
		if heroViper == nil {
			log.Printf("警告: 无法获取英雄 '%s' 的配置子树", name)
			continue
		}

		// 创建配置实例
		cfg := &ChampionConfig{Name: name}

		// 解析基础属性
		if err := parseBaseAttributes(heroViper, cfg); err != nil {
			log.Printf("英雄 %s 基础属性解析失败: %v", name, err)
			continue
		}

		// 解析防御属性
		if err := parseDefence(heroViper, cfg); err != nil {
			log.Printf("英雄 %s 防御属性解析失败: %v", name, err)
			continue
		}

		// 解析技能列表
		if err := parseSkills(heroViper, cfg); err != nil {
			log.Printf("英雄 %s 技能解析失败: %v", name, err)
			continue
		}

		champions[name] = cfg
		bundles[name] = cfg.RegisterBundle()
	}
}

// 解析基础属性
func parseBaseAttributes(v *viper.Viper, cfg *ChampionConfig) error {
	// 获取循环标志
	cfg.Loop = v.GetInt("Loop") == 1
	return nil
}

// 解析防御属性
func parseDefence(v *viper.Viper, cfg *ChampionConfig) error {
	stat := v.Get("Stat")
	if stat == nil {
		panic("Stat字段不存在")
	}
	cfg.Defence = &DefenceConfig{}
	parts := strings.Split(stat.(string), " ")
	if len(parts) == 2 {
		parts = append(parts, "0.6")
	}
	if hp, err := strconv.Atoi(parts[0]); err == nil {
		cfg.Defence.Hp = hp
	}
	if ar, err := strconv.Atoi(parts[1]); err == nil {
		cfg.Defence.Armor = ar
	}
	if speed, err := strconv.ParseFloat(parts[2], 64); err == nil {
		cfg.Speed = speed
	}

	return nil
}

// 解析技能列表
func parseSkills(v *viper.Viper, cfg *ChampionConfig) error {
	skills := v.Get("Skills")
	if skills == nil {
		return nil // 技能是可选的
	}

	// 转换为切片
	skillList, ok := skills.([]interface{})
	if !ok {
		return fmt.Errorf("skills格式错误")
	}

	for _, s := range skillList {
		skillMap, ok := s.(map[string]interface{})
		if !ok {
			return fmt.Errorf("技能格式错误")
		}

		sc := &SkillConfig{}

		// 解析法力值 (格式: "初始值 最大值")
		if mana, ok := skillMap["mana"].(string); ok {
			parts := strings.Fields(mana)
			if len(parts) > 0 {
				// 只取最大值作为技能法力消耗
				if val, err := strconv.Atoi(parts[len(parts)-1]); err == nil {
					sc.Mana = val
				}
			}
			if len(parts) > 1 {
				if val, err := strconv.Atoi(parts[0]); err == nil {
					// 初始蓝量
					cfg.Mana = val
				}
			}
		} else if mana, ok := skillMap["mana"].(int); ok {
			sc.Mana = mana
		}

		// 解析成长表达式
		if grow, ok := skillMap["grow"]; ok {
			switch v := grow.(type) {
			case string:
				sc.Grow = v
			case int:
				sc.Grow = strconv.Itoa(v)
			}
		}

		// 解析治疗表达式
		if heal, ok := skillMap["heal"]; ok {
			switch v := heal.(type) {
			case string:
				sc.Heal = v
			case int:
				sc.Heal = apScaling + strconv.Itoa(v)
			}
		}

		// 解析护盾 (格式: "值, 持续时间")
		if shield, ok := skillMap["shield"].(string); ok {
			parts := strings.SplitN(shield, ",", 2)
			if len(parts) > 0 {
				sd := strings.TrimSpace(parts[0])
				if _, err := strconv.Atoi(sd); err == nil {
					sd = apScaling + sd
				}
				sc.Shield = sd
			}
			if len(parts) > 1 {
				duration := strings.Fields(parts[1])
				sc.Duration, _ = strconv.Atoi(duration[0])
			}
		}

		// 解析BUFF效果
		if buff, ok := skillMap["buff"].(string); ok {
			sc.Buff = parseBuffConfig(buff)
		}

		// 解析护盾 (格式: "值, 持续时间")
		if swing, ok := skillMap["swing"].(int); ok {
			sc.Swing = swing
		}

		cfg.Skills = append(cfg.Skills, sc)
	}

	return nil
}

// 解析BUFF配置
func parseBuffConfig(buff string) *BuffConfig {
	parts := strings.SplitN(buff, ",", 2)
	if len(parts) != 2 {
		return nil
	}

	// 解析效果标识
	effect := strings.TrimSpace(parts[0])

	// 解析持续时间
	durationParts := strings.Fields(strings.TrimSpace(parts[1]))
	if len(durationParts) < 2 {
		durationParts = append(durationParts, "")
	}

	duration, err := strconv.Atoi(durationParts[0])
	if err != nil {
		return nil
	}

	return &BuffConfig{
		Effect:   effect,
		Duration: duration,
		Reduce:   transfer[durationParts[1]],
	}
}

func (c *ChampionConfig) RegisterBundle() *Bundle {
	bundle := &Bundle{championMeta: newChamp()}
	bundle.health = c.Defence.Hp
	bundle.armor = c.Defence.Armor
	bundle.speed = c.Speed
	if bundle.speed == 0 {
		// 默认攻速0.6
		bundle.speed = 0.6
	}
	bundle.initMana = c.Mana

	// 存在同名bundle时覆盖
	bundles[c.Name] = bundle
	bundle.name = c.Name

	if len(c.Skills) == 0 {
		return bundle
	}
	bundle.skill = c.Skills[0].Create()
	head := bundle.skill
	current := bundle.skill
	for i := 1; i < len(c.Skills); i++ {
		current.next = c.Skills[i].Create()
		current = current.next
	}
	if c.Loop {
		current.next = head
	}
	return bundle
}

func (s SkillConfig) Create() *skill {
	meta := &skill{}
	meta.name = "Skill"
	meta.mana = s.Mana
	meta.swing = s.Swing
	meta.Heal = s.Heal
	meta.Grow = s.Grow
	meta.Shield = s.Shield
	meta.duration = s.Duration

	if s.Buff == nil {
		return meta
	}

	event := TimeGoE
	switch s.Buff.Reduce {
	case "time", "":
	case "attack":
		event = AttackE
	case "cast":
		event = AfterCastE
	default:
		panic(fmt.Sprintf("unknown reduce: %s", s.Buff.Reduce))
	}
	meta.buff = NewBuff(event, s.Buff.Duration)
	meta.buff.parseAttr(s.Buff.Effect)

	return meta
}
